/*
三色LED交通灯模块（红绿黄灯）2
加入行人按键
*/

int redled =11; 
int yellowled =12; 
int greenled =13; 

// 定义行人按键引脚
const int PED_BUTTON_PIN = 2;

// 当前倒计时剩余时间
int countdownRemaining = 0;

// 当前红绿灯状态
enum LightState {
  RED,
  GREEN,
  YELLOW,
  OFF
};
LightState currentLightState = RED; 

void setup() {

  Serial.begin(9600); //启动串口通讯，传输波特率9600
  Serial.println("Please input serial data.");
 
  //按钮引脚(行人通行使用)
  pinMode(PED_BUTTON_PIN, INPUT_PULLUP);

  //数码管引脚
  for (int i = 2; i <= 9; i++) {
    pinMode(i, OUTPUT);
  }

  //交通灯引脚
  pinMode(redled, OUTPUT);
  pinMode(yellowled, OUTPUT); 
  pinMode(greenled, OUTPUT); 


  Serial.begin(9600);
  Serial.println("Please input serial data.");
}

// the loop function runs over and over again forever
void loop() {
  
  startNewCycle();
  updateSmg(countdownRemaining);
  delay(200);
}

void updateSmg(int miao) {
  int myNumber = miao;
  while(myNumber > 0){
    displayNumber(myNumber);
    delay(500);
    displayClear();
    myNumber--;

    if(updatePedestrianButton()) {
      break;
    }

    delay(500);
  }
}

void startNewCycle() {
  switch (currentLightState) {
    case RED:
      currentLightState = GREEN;
      countdownRemaining = 9;
      break;
    case GREEN:
      currentLightState = YELLOW;
      countdownRemaining = 3;
      break;
    case YELLOW:
      currentLightState = RED;
      countdownRemaining = 9;
      break;
    default:
      break;
  }

  switch (currentLightState) {
    case RED:
      digitalWrite(redled, HIGH);
      digitalWrite(yellowled, LOW);
      digitalWrite(greenled, LOW);
      break;
    case GREEN:
      digitalWrite(redled, LOW);
      digitalWrite(yellowled, LOW);
      digitalWrite(greenled, HIGH);
      break;
    case YELLOW:
      digitalWrite(redled, LOW);
      digitalWrite(yellowled, HIGH);
      digitalWrite(greenled, LOW);
      break;
    default:
      digitalWrite(redled, LOW);
      digitalWrite(yellowled, LOW);
      digitalWrite(greenled, LOW);
      break;
  }
}

bool updatePedestrianButton() {
  if (digitalRead(PED_BUTTON_PIN) == LOW) {
    // 如果在红灯期间按下按钮且当前为红灯，则提前切换至绿灯
    currentLightState = GREEN;
    
    digitalWrite(redled, LOW);
    digitalWrite(yellowled, LOW);
    digitalWrite(greenled, HIGH);
    int myNumber = 9;
    while(myNumber > 0){
      displayNumber(myNumber);
      delay(500);
      displayClear();
      myNumber--;
  
      delay(500);
    } 
    return true;
    
  }
  return false;
  
}

void displayClear(){
  // 清理显示内容
  digitalWrite(3, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH); 
  digitalWrite(6, HIGH); 
  digitalWrite(7, HIGH); 
  digitalWrite(8, HIGH); 
  digitalWrite(9, HIGH); 
}

void displayNumber(int number){
  switch(number){
    case 1:
      digitalWrite(4, LOW);
      digitalWrite(7, LOW); 
      break;   
    case 2:
      digitalWrite(3, LOW);
      digitalWrite(4, LOW); 
      digitalWrite(5, LOW); 
      digitalWrite(8, LOW); 
      digitalWrite(9, LOW); 
      break;   
    case 3:
      digitalWrite(3, LOW);
      digitalWrite(4, LOW); 
      digitalWrite(5, LOW); 
      digitalWrite(7, LOW); 
      digitalWrite(8, LOW); 
      break;   
    case 4:
      digitalWrite(4, LOW); 
      digitalWrite(5, LOW); 
      digitalWrite(6, LOW); 
      digitalWrite(7, LOW); 
      break;  
    case 5:
      digitalWrite(3, LOW);
      digitalWrite(5, LOW); 
      digitalWrite(6, LOW); 
      digitalWrite(7, LOW); 
      digitalWrite(8, LOW); 
      break;
    case 6:
      digitalWrite(3, LOW);
      digitalWrite(5, LOW); 
      digitalWrite(6, LOW); 
      digitalWrite(7, LOW); 
      digitalWrite(8, LOW); 
      digitalWrite(9, LOW); 
      break;    
    case 7:
      digitalWrite(3, LOW);
      digitalWrite(4, LOW); 
      digitalWrite(7, LOW);  
      break;
    case 8:
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW); 
      digitalWrite(6, LOW); 
      digitalWrite(7, LOW); 
      digitalWrite(8, LOW); 
      digitalWrite(9, LOW); 
      break;
    case 9:
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW); 
      digitalWrite(6, LOW); 
      digitalWrite(7, LOW); 
      digitalWrite(8, LOW); 
      break;
    case 0:
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      digitalWrite(6, LOW); 
      digitalWrite(7, LOW); 
      digitalWrite(8, LOW); 
      digitalWrite(9, LOW); 
      break;
    default:
      digitalWrite(5, LOW);    
    }
}
